package winOrDie.tests;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import rice.environment.Environment;
import rice.pastry.NodeIdFactory;
import rice.pastry.PastryNode;
import rice.pastry.PastryNodeFactory;
import rice.pastry.socket.SocketPastryNodeFactory;
import rice.pastry.standard.RandomNodeIdFactory;
import winOrDie.Net.WoD_Net_Protocol_ASCII;
import winOrDie.Net.P2P.WoD_Scribe_Channel;

public class Net_test_P2P {


	WoD_Scribe_Channel woDScribeClient = null;


	public Net_test_P2P(
			int bindport, 
			InetSocketAddress bootaddress,
			Environment env) 
	throws Exception 
	{

		// Generate the NodeIds Randomly
		NodeIdFactory nidFactory = new RandomNodeIdFactory(env);

		// construct the PastryNodeFactory, this is how we use rice.pastry.socket
		PastryNodeFactory factory = new SocketPastryNodeFactory(nidFactory, bindport, env);


		PastryNode node = factory.newNode();

		woDScribeClient = new WoD_Scribe_Channel(node);

		node.boot(bootaddress);
		// the node may require sending several messages to fully boot into the ring
		synchronized(node) {
			while(!node.isReady() && !node.joinFailed()) {
				// delay so we don't busy-wait
				node.wait(500);

				// abort if can't join
				if (node.joinFailed()) {
					throw new IOException("Could not join the FreePastry ring.  Reason:"+node.joinFailedReason()); 
				}
			}       
		}

		System.out.println("Finished creating new node: " + node);

		/**
		 * Check our bind address
		 */
		InetAddress inetAddress = ((SocketPastryNodeFactory)factory).getBindAddress();
		System.out.println("Node IP Address: " + inetAddress.getHostAddress());
		
		woDScribeClient.subscribe();

		chat();
	}





	private void chat()
	{
		// open a reader over the keyboard (System.in) stream.
		BufferedReader reader= new BufferedReader(
				new InputStreamReader(System.in)); 

		boolean exit_chat = false;

		String input_Text = null;
		while (!exit_chat) {
			try {
				input_Text = reader.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				exit_chat = true;
			}
			String Chat_Message = WoD_Net_Protocol_ASCII.GameRoom.Chat + " " + input_Text; 

			try {

				if (Chat_Message.startsWith("/exit"))
				{
					exit_chat = true;
					woDScribeClient.sendMulticast(Chat_Message);
				}
				else
				{
					woDScribeClient.sendMulticast(Chat_Message);
				}

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				exit_chat = true;
			}
		}

	}





	public static void main(String[] args) 
	{
		// Loads pastry configurations
		Environment env = new Environment();

		// disable the UPnP setting (in case you are testing this on a NATted LAN)
		env.getParameters().setString("nat_search_policy","never");
		try {
			// the port to use locally
			int bindport = Integer.parseInt(args[0]);

			// build the bootaddress from the command line args
			InetAddress bootaddr = InetAddress.getByName(args[1]);
			int bootport = Integer.parseInt(args[2]);
			InetSocketAddress bootaddress = new InetSocketAddress(bootaddr, bootport);

			// launch our node!
			Net_test_P2P netTestP2P = new Net_test_P2P(bindport, bootaddress, env);
		} catch (Exception e) {
			System.out.println("Error " + e.getMessage());
			// remind user how to use
			System.out.println("Usage:");
			System.out.println("java [-cp FreePastry-<version>.jar] winOrDie.tests.Net_test_P2P localbindport bootIP bootPort");

		}

	}

}
